#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/sched.h>

#define DEVICE_NAME "deadlock_dev"
static int major;
static struct class *cls;
static spinlock_t my_spinlock;

// // 场景1：重复获取同一把锁
// static int device_open(struct inode *inode, struct file *filp) {
//     spin_lock(&my_spinlock);    // 第一次获取锁
//     spin_lock(&my_spinlock);    // 第二次获取锁（死锁点）[2,7](@ref)
//     printk(KERN_INFO "Lock acquired\n");
//     return 0;
// }

// //场景2：获取自旋锁关闭了内核抢占,此时不会发生进程切换系统卡死
// static int device_open(struct inode* inode, struct file* filp) {
//     spin_lock(&my_spinlock);
//     while(1) {};
//     return 0;
// }

// // 场景3:获取自旋锁调用睡眠接口导致进程切换,调用两次app系统卡死
// static int device_open(struct inode* inode, struct file* filp) {
//     spin_lock(&my_spinlock);
//     int i = 100;
//     for (; i > 0; --i)
//     {
//         printk(KERN_EMERG "%d",i);
//     }
//     return 0;
// }


// 场景4:获取自旋锁主动调用schedule();
static int device_open(struct inode* inode, struct file* filp) {
printk(KERN_INFO "Entering device_open\n");  // 添加日志
    spin_lock(&my_spinlock);
    schedule();
    printk(KERN_INFO "Exiting device_open (lock not released!)\n");  // 此处不应执行
    return 0;
}

static struct file_operations fops = {
    .open = device_open,
};

static int __init spin____init(void) {
    spin_lock_init(&my_spinlock);    // 初始化自旋锁[2,5](@ref)
    major = register_chrdev(0, DEVICE_NAME, &fops);
    cls = class_create(THIS_MODULE, DEVICE_NAME);
    device_create(cls, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);
    return 0;
}

static void __exit driver_exit(void) {
    device_destroy(cls, MKDEV(major, 0));
    class_destroy(cls);
    unregister_chrdev(major, DEVICE_NAME);
}

module_init(spin____init);
module_exit(driver_exit);
MODULE_LICENSE("GPL");